package com.example.back.service.impl;

import com.example.back.dto.req.ConfigReq;
import com.example.back.jpa.CMSRepository;
import com.example.back.jpa.ConfigRepository;
import com.example.back.jpa.HospitalConfigRepository;
import com.example.back.jpa.HospitalRepository;
import com.example.back.mapper.BusConfigMapper;
import com.example.back.mapper.ConfigMapper;
import com.example.back.service.BusConfigService;
import com.example.common.entity.CMS;
import com.example.common.entity.Config;
import com.example.common.entity.Hospital;
import com.example.common.entity.HospitalConfig;
import com.example.common.enums.AType;
import com.example.common.support.ApiException;
import com.example.common.utils.CheckUtils;
import com.example.common.utils.UIDUtils;

import org.javers.spring.annotation.JaversAuditable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class BusConfigServiceImpl implements BusConfigService {

    @Resource
    private UIDUtils uidUtils;

    @Resource
    private HospitalRepository hospitalRepository;

    @Resource
    private HospitalConfigRepository hospitalConfigRepository;

    @Resource
    private ConfigMapper configMapper;

    @Resource
    private CMSRepository cMSRepository;

    @Resource
    private ConfigRepository configRepository;

    @Resource
    private BusConfigMapper busConfigMapper;

    @Override
    public Map<String, Object> GetConfig() {
        Hospital h = hospitalRepository.findByLast();
        HospitalConfig config = hospitalConfigRepository.findById(h.getId())
                .orElseThrow(() -> new ApiException(1, "医院信息不完整"));
        List<Map<String, Object>> TitleGroup = configMapper.TitleGroup();

        List<Map<String, Object>> list = new ArrayList<>();
        Map<String, Object> m = new HashMap<>();
        m.put("AType", AType.NetReferral.getValue());
        m.put("aName", AType.valueToDesc(AType.NetReferral.getValue()));
        m.put("Service", config.getNetConfig());
        m.put("MustOpen", config.getNetMustOpen());
        m.put("SelfPrice", config.getNetSelfPrice());
        m.put("SetType", config.getNetSetType());
        m.put("Valid", config.getNetValid() / 60);
        m.put("Price", config.getNetPrice());
        List<Map<String, Object>> TitleNet = new ArrayList<>();
        TitleGroup.forEach(n -> {
            Map<String, Object> t = new HashMap<>();
            t.put("Title", n.get("Title"));
            t.put("Price", n.get("TitleNetPrice"));
            TitleNet.add(t);
        });
        m.put("Title", TitleNet);
        list.add(m);

        m = new HashMap<>();
        m.put("AType", AType.ImgText.getValue());
        m.put("aName", AType.valueToDesc(AType.ImgText.getValue()));
        m.put("Service", config.getImgText());
        m.put("MustOpen", config.getImgTextMustOpen());
        m.put("SelfPrice", config.getImgTextSelfPrice());
        m.put("SetType", config.getImgTextSetType());
        m.put("Valid", config.getImgTextValid() / 60);
        m.put("Price", config.getImgTextPrice());
        List<Map<String, Object>> TitleImgText = new ArrayList<>();
        TitleGroup.forEach(n -> {
            Map<String, Object> t = new HashMap<>();
            t.put("Title", n.get("Title"));
            t.put("Price", n.get("TitleImgTextPrice"));
            TitleImgText.add(t);
        });
        m.put("Title", TitleImgText);
        list.add(m);

        m = new HashMap<>();
        m.put("AType", AType.Phone.getValue());
        m.put("aName", AType.valueToDesc(AType.Phone.getValue()));
        m.put("Service", config.getPhone());
        m.put("MustOpen", config.getPhoneMustOpen());
        m.put("SelfPrice", config.getPhoneSelfPrice());
        m.put("SetType", config.getPhoneSetType());
        m.put("Valid", config.getPhoneValid());
        m.put("Price", config.getPhonePrice());
        List<Map<String, Object>> TitlePhone = new ArrayList<>();
        TitleGroup.forEach(n -> {
            Map<String, Object> t = new HashMap<>();
            t.put("Title", n.get("Title"));
            t.put("Price", n.get("TitlePhonePrice"));
            TitlePhone.add(t);
        });
        m.put("Title", TitlePhone);
        list.add(m);

        m = new HashMap<>();
        m.put("AType", AType.Video.getValue());
        m.put("aName", AType.valueToDesc(AType.Video.getValue()));
        m.put("Service", config.getVideo());
        m.put("MustOpen", config.getVideoMustOpen());
        m.put("SelfPrice", config.getVideoSelfPrice());
        m.put("SetType", config.getVideoSetType());
        m.put("Valid", config.getVideoValid());
        m.put("Price", config.getVideoPrice());
        List<Map<String, Object>> TitleVideo = new ArrayList<>();
        TitleGroup.forEach(n -> {
            Map<String, Object> t = new HashMap<>();
            t.put("Title", n.get("Title"));
            t.put("Price", n.get("TitleVideoPrice"));
            TitleVideo.add(t);
        });
        m.put("Title", TitleVideo);
        list.add(m);

        CMS cms = configMapper.findCms();
        Map<String, Object> cmsm = new HashMap<>();
        cmsm.put("ID", cms.getId());
        cmsm.put("NContent", cms.getNContent());

        Map<String, Object> Self = new HashMap<>();
        Self.put("SelfName", h.getSelfName());
        Self.put("SelfAddress", h.getSelfAddress());

        Map<String, Object> res = new HashMap<>();
        res.put("HospitalID", h.getId());
        res.put("config", list);
        res.put("cms", cmsm);
        res.put("Self", Self);

        return res;
    }

    @Override
    @JaversAuditable
    public String SaveCms(CMS cms) {
        cms.setTypes(3);
        try {
            cMSRepository.save(cms);
        } catch (Exception e) {
            return "修改失败";
        }
        return "";
    }

    @Override
    @JaversAuditable
    public String SaveSelf(Hospital req) {
        Hospital h = hospitalRepository.findById(req.getId()).orElseThrow(() -> new ApiException(1, "医院信息不完整"));
        h.setSelfName(req.getSelfName());
        h.setSelfAddress(req.getSelfAddress());

        try {
            hospitalRepository.save(h);
        } catch (Exception e) {
            return "修改失败";
        }
        return "";
    }

    @Override
    @JaversAuditable
    @Transactional(rollbackFor = Exception.class)
    public String SaveConfig(ConfigReq req) {
        HospitalConfig config = hospitalConfigRepository.findById(req.getHospitalID()).orElseThrow(() -> new ApiException(1, "医院信息不完整"));
        Integer Valid = null;
        AType aType = AType.valueByType(req.getAType());
        switch (Objects.requireNonNull(aType)) {
            case NetReferral:
                config.setNetConfig(req.getService());
                if (req.getService()) {
                    config.setNetMustOpen(req.getMustOpen());
                    config.setNetSelfPrice(req.getSelfPrice());
                    config.setNetSetType(req.getSetType());
                    Valid = req.getValid() * 60;
                    config.setNetValid(Valid);
                    config.setNetPrice(req.getPrice());
                }
                break;
            case ImgText:
                config.setImgText(req.getService());
                if (req.getService()) {
                    config.setImgTextMustOpen(req.getMustOpen());
                    config.setImgTextSelfPrice(req.getSelfPrice());
                    config.setImgTextSetType(req.getSetType());
                    Valid = req.getValid() * 60;
                    config.setImgTextValid(Valid);
                    config.setImgTextPrice(req.getPrice());
                }
                break;
            case Phone:
                config.setPhone(req.getService());
                if (req.getService()) {
                    config.setPhoneMustOpen(req.getMustOpen());
                    config.setPhoneSelfPrice(req.getSelfPrice());
                    config.setPhoneSetType(req.getSetType());
                    Valid = req.getValid();
                    config.setPhoneValid(Valid);
                    config.setPhonePrice(req.getPrice());
                }
                break;
            case Video:
                config.setVideo(req.getService());
                if (req.getService()) {
                    config.setVideoMustOpen(req.getMustOpen());
                    config.setVideoSelfPrice(req.getSelfPrice());
                    config.setVideoSetType(req.getSetType());
                    Valid = req.getValid();
                    config.setVideoValid(Valid);
                    config.setVideoPrice(req.getPrice());
                }
                break;
            default:
                break;
        }
        hospitalConfigRepository.save(config);
        if (req.getService()) {
            List<Config> list;
            // 强制医生开通服务
            if (req.getMustOpen()) {
                switch (aType) {
                    case NetReferral:
                        list = configRepository.findAllByNetReferral(Boolean.FALSE);
                        list = list.stream().peek(p -> p.setNetReferral(Boolean.TRUE)).collect(Collectors.toList());
                        if (!CollectionUtils.isEmpty(list)) {
                            configRepository.saveAll(list);
                        }
                        break;
                    case ImgText:
                        list = configRepository.findAllByImgText(Boolean.FALSE);
                        list = list.stream().peek(p -> p.setImgText(Boolean.TRUE)).collect(Collectors.toList());
                        if (!CollectionUtils.isEmpty(list)) {
                            configRepository.saveAll(list);
                        }
                        break;
                    case Phone:
                        list = configRepository.findAllByPhone(Boolean.FALSE);
                        list = list.stream().peek(p -> p.setPhone(Boolean.TRUE)).collect(Collectors.toList());
                        if (!CollectionUtils.isEmpty(list)) {
                            configRepository.saveAll(list);
                        }
                        break;
                    case Video:
                        list = configRepository.findAllByVideo(Boolean.FALSE);
                        list = list.stream().peek(p -> p.setVideo(Boolean.TRUE)).collect(Collectors.toList());
                        if (!CollectionUtils.isEmpty(list)) {
                            configRepository.saveAll(list);
                        }
                        break;
                    default:
                        break;
                }
            }
            //医院统一设置价格和时间
            if (!req.getSelfPrice()) {
                Integer finalValid = Valid;
                // 统一设置
                if (1 == req.getSetType()) {
                    List<Config> allList = configRepository.findAll();
                    switch (aType) {
                        case NetReferral:
                            allList = allList.stream().peek(p -> {
                                p.setReferralValid(finalValid);
                                p.setReferralPrice(req.getPrice());
                            }).collect(Collectors.toList());
                            if (!CollectionUtils.isEmpty(allList)) {
                                configRepository.saveAll(allList);
                            }
                            break;
                        case ImgText:
                            allList = allList.stream().peek(p -> {
                                p.setImgTextValid(finalValid);
                                p.setImgTextPrice(req.getPrice());
                            }).collect(Collectors.toList());
                            if (!CollectionUtils.isEmpty(allList)) {
                                configRepository.saveAll(allList);
                            }
                            break;
                        case Phone:
                            allList = allList.stream().peek(p -> {
                                p.setPhoneValid(finalValid);
                                p.setPhonePrice(req.getPrice());
                            }).collect(Collectors.toList());
                            if (!CollectionUtils.isEmpty(allList)) {
                                configRepository.saveAll(allList);
                            }
                            break;
                        case Video:
                            allList = allList.stream().peek(p -> {
                                p.setVideoValid(finalValid);
                                p.setVideoPrice(req.getPrice());
                            }).collect(Collectors.toList());
                            if (!CollectionUtils.isEmpty(allList)) {
                                configRepository.saveAll(allList);
                            }
                            break;
                        default:
                            break;
                    }
                }
                //按医生级别设置
                if (2 == req.getSetType()) {
                    CheckUtils.checkNull(req.getTList(), new ApiException(1, "修改失败，参数错误"));
                    req.getTList().forEach(c -> busConfigMapper.updateDoctorConfig(finalValid, c.getPrice(), c.getTitle(), req.getAType()));
                }
            }
        }
        return null;
    }
}
